package com.greate.community.controller;

import com.alibaba.fastjson.JSONArray;
import com.greate.community.entity.Event;
import com.greate.community.entity.Page;
import com.greate.community.entity.Result;
import com.greate.community.entity.User;
import com.greate.community.entity.dto.FollowDTO;
import com.greate.community.event.EventProducer;
import com.greate.community.jwt.JwtUser;
import com.greate.community.service.FollowService;
import com.greate.community.service.MessageService;
import com.greate.community.service.UserService;
import com.greate.community.constant.CommunityConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * 关注(目前只做了关注用户)
 */
@RestController
public class FollowController extends BaseController implements CommunityConstant {

    @Autowired
    private FollowService followService;

    @Autowired
    private UserService userService;

    @Autowired
    private MessageService messageService;

    @Autowired
    private EventProducer eventProducer;

    /**
     * 关注
     *
     * @return
     */
    @PostMapping("/follow")
    @ResponseBody
    public Result follow(@RequestBody @Validated FollowDTO followDTO) {
        int entityType = followDTO.getEntityType();
        int entityId = followDTO.getEntityId();

        JwtUser user = getUser();
        // 判断当前实体是否存在
        if (isNotExist(entityType, entityId)) {
            return new Result("fail", "1", "实体不存在");
        }

        // 判断当前登录用户是否关注该实体类型的实体id
        boolean hasFollowed = hasFollowed(entityType, entityId);
        if (hasFollowed) {
            return new Result("success", Result.SUCCESS, "您已关注过该用户，无需再次关注");
        }

        // 未关注该用户，执行关注操作
        followService.followOrUnfollow(user.getId(), entityType, entityId);

        // 判断是否已经存在由 getUser().getId() 用户关注 entityId 用户生成的 follow 类型系统通知
        boolean hasFollowMessage = messageService.hasFollowMessage(entityId, getUser().getId());
        if (!hasFollowMessage) {
            // 尚无该关注通知，则触发关注事件（系统通知）
            Event event = new Event()
                    .setTopic(TOPIC_FOLLOW)
                    .setUserId(getUser().getId())
                    .setEntityType(entityType)
                    .setEntityId(entityId)
                    .setEntityUserId(entityId);
            eventProducer.fireEvent(event);
        }
        return new Result("success", Result.SUCCESS, "关注用户成功");
    }

    /**
     * 取消关注
     *
     * @return
     */
    @PostMapping("/unfollow")
    @ResponseBody
    public Result unfollow(@RequestBody @Validated FollowDTO followDTO) {
        int entityType = followDTO.getEntityType();
        int entityId = followDTO.getEntityId();
        // 判断当前实体是否存在
        if (isNotExist(entityType, entityId)) {
            return new Result("fail", "1", "实体不存在");
        }
        // 判断当前登录用户是否关注该实体类型的实体id
        boolean hasFollowed = hasFollowed(entityType, entityId);
        if (hasFollowed) {
            //已经关注该用户，执行取关操作
            followService.followOrUnfollow(getUser().getId(), entityType, entityId);

            return new Result("success", Result.SUCCESS, "已取消关注");
        } else {
            //未关注该用户
            return new Result("success", Result.SUCCESS, "您尚未关注该用户，无需取消关注");
        }
    }

    /**
     * 某个用户的关注列表（人）
     *
     * @param userId
     * @param page
     * @return
     */
    @GetMapping("/followees/{userId}")
    @ResponseBody
    public Result getFollowees(@PathVariable("userId") int userId, Page page) {
        User user = userService.findUserById(userId);
        if (user == null) {
            throw new RuntimeException("该用户不存在");
        }

        page.setPath("/followees/" + userId);
        page.setRows((int) followService.findFolloweeCount(userId, ENTITY_TYPE_USER));

        // 获取关注列表
        List<Map<String, Object>> userList = followService.findFollowees(userId, page.getOffset(), page.getLimit());

        if (userList != null && !userList.isEmpty()) {
            for (Map<String, Object> map : userList) {
                User u = (User) map.get("user"); // 被关注的用户
                map.put("hasFollowed", hasFollowed(u.getId())); // 判断当前登录用户是否已关注这个关注列表中的某个用户
            }
        }
        JSONArray result = (JSONArray) JSONArray.toJSON(userList);
        page.setResult(result);

        return new Result("success", Result.SUCCESS, page);
    }

    /**
     * 某个用户的粉丝列表
     *
     * @param userId
     * @param page
     * @return
     */
    @GetMapping("/followers/{userId}")
    @ResponseBody
    public Result getFollowers(@PathVariable("userId") int userId, Page page) {
        User user = userService.findUserById(userId);
        if (user == null) {
            throw new RuntimeException("该用户不存在");
        }

        page.setPath("/followers/" + userId);
        page.setRows((int) followService.findFollowerCount(ENTITY_TYPE_USER, userId));

        // 获取关注列表
        List<Map<String, Object>> userList = followService.findFollowers(userId, page.getOffset(), page.getLimit());

        if (userList != null) {
            for (Map<String, Object> map : userList) {
                User u = (User) map.get("user"); // 被关注的用户
                map.put("hasFollowed", hasFollowed(u.getId())); // 判断当前登录用户是否已关注这个关注列表中的某个用户
            }
        }
        JSONArray result = (JSONArray) JSONArray.toJSON(userList);
        page.setResult(result);

        return new Result("success", Result.SUCCESS, page);
    }

    /**
     * 判断当前登录用户是否已关注某个用户
     *
     * @param userId 某个用户
     * @return
     */
    private boolean hasFollowed(int userId) {
        if (getUser() == null) {
            return false;
        }

        return followService.hasFollowed(getUser().getId(), ENTITY_TYPE_USER, userId);
    }


    /**
     * 判断当前登录用户是否已关注某类型实体的实体id
     *
     * @param entityType 实体类型
     * @param entityId   实体id
     * @return
     */
    private boolean hasFollowed(int entityType, int entityId) {
        if (getUser() == null) {
            return false;
        }

        return followService.hasFollowed(getUser().getId(), entityType, entityId);
    }

    /**
     * 判断当前目标实体是否存在
     *
     * @param entityType 实体类型
     * @param entityId   实体id
     * @return
     */
    private boolean isNotExist(int entityType, int entityId) {
        if (entityType == 3) {
            // 关注的用户是自己
            if (getUser() == null || getUser().getId() == entityId) {
                return true;
            }
            return userService.findUserById(entityId) == null;
        }
        return true;
    }
}
